iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
自我挑戰組

菜雞也能優雅的征服RxJS系列 第 16

菜雞也能優雅的征服RxJS - day16 : 安插個觀察點 - tap (下集)

  • 分享至 

  • xImage
  •  

  • 今天來繼續說說tap下集

case4: 來個side effect改變一下

  • 我們使用前幾天實作2:scan - countdown為例子來觀察一下。

stackblitz

import { interval, map, scan, filter, tap } from 'rxjs';

// get element
const countdown = document.getElementById('countdown');
const message = document.getElementById('message');

// final countdown
console.log(' === case4: 模擬在pipe途中,使用tap修改side effect ===');
const finalCountdown$ = interval(1000).pipe(
  map((val) => 1),
  scan((accum, current) => accum - current, 6),
  filter((val) => val >= 0),
  tap((val) => {
    // (2)利用tap在pipe途中,進行side effect的設定,由於我們沒有修改stream的值,故不影響!
    countdown.innerHTML = `${val}`;
    if (!val) message.innerHTML = 'HAPPY NEW YEAR!!';
  }),
  map((val) => val + 10) //<-- (3)模擬額外的動作
);

// show on console
finalCountdown$.subscribe(console.log);

//(1) 取消使用subscribe設定side effect
// modify HTML
// finalCountdown$.subscribe((val) => {
//   countdown.innerHTML = `${val}`;
//   if (!val) message.innerHTML = 'HAPPY NEW YEAR!!';
// });

case5: 觀察一個有趣的地方

解析

我們原本於subscribe中進行HTML side effect的設定,現在做些修正:

  1. comment掉(如(1)),取消使用subscribe設定side effect
  2. 放入tap之中進行side effect的修改
  3. 加一個map模擬後續動作,來驗證tap可於任意位置進行side effect的設定

  • 注意到了嗎,HTML可以在tap中進行修改,且不影響我們後續map的輸出,超方便的!

case6: 加入complete建立觀察者試試

  • 昨天提到,tap(observer)也是被允許的,我們延續剛剛的例子,順勢地建立出nextcompletefunc,來看看有什麼有趣的情形☕
    stackblitz
  ...
  tap({
    next: (val) => {
      // (2)利用tap在pipe途中,進行side effect的設定,由於我們沒有修改stream的值,故不影響!
      countdown.innerHTML = `${val}`;
      if (!val) message.innerHTML = 'HAPPY NEW YEAR!!';
    },
    complete: () => console.log('completed!'), //<-- 注意complete何時被觸發
  }),
  ...

complete呢!? 啥~還有數據/images/emoticon/emoticon19.gif

  • 注意到了嗎?建立好的observer卻始終沒有觸發complete,這倒底是什麼原因??/images/emoticon/emoticon23.gif
  • 我們在filter上方,放置一個tap((val)=>console.log(val))看看,唉呦,都用了filter了,數據怎一直冒出來!!??這不是弄糊塗我了嗎??
const finalCountdown$ = interval(1000).pipe(
  map((val) => 1),
  scan((accum, current) => accum - current, 6),
  tap((val) => console.log('before-filter:', val)),  //<-- tap放在此觀察看看,數據仍不斷出現
  filter((val) => val >= 0),
  ...
  map((val) => val + 10)
);

解析

  • 這原因就是,filter只幫我們過濾數據到後方,但並未中止源頭的observable,因此,interval持續地發送數據,也因此tap(observer)的complete不會被觸發!✍

  • 這也是為什麼,學習RxJS常看完說明之後,但在實作時卻又常摸不著頭緒(就跟學妹一樣,明明牽了小手,卻又說~"學長~我想我們只是朋友"),所以建議還是親手體驗,才能邁向天長地久XD。

✍Recap

  • tap可以協助我們執行side effect,設定HTML格式發出錯誤訊息
  • tap(observer)是被允許執行的。
  • case5中,observer裡的complete不被觸發,是因為filter的特性。

好啦! 完成第16天的任務啦,超越50%,再加把勁,繼續往終點前進!!


上一篇
day15: 安插個觀察點 - tap (上集)
下一篇
菜雞也能優雅的征服RxJS - day17: 設定領取數量take
系列文
菜雞也能優雅的征服RxJS32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言